package nl.ceasaro.poker.ranking;

import nl.ceasaro.playingcards.Card;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * Created by Zerg.
 * User: cees
 * Date: Jul 31, 2007
 * Time: 10:24:36 PM
 *
 * @todo Document this class
 */
public class PokerRankCalculator
{
   /**
    * @param cards     cards to check for a straight
    * @param replenish if set to <i>true</i> the missing cards are filled in automatically
    * @return a set of {@link Card}'s representing a straight, if one is found. If replenish is
    *         set to <i>true</i> the complete straight is return with the replenished cards.
    */
   public static ArrayList<Card> getStraight(List<Card> cards, boolean replenish)
   {
      Collections.sort(cards);
      ArrayList<Card> straight = new ArrayList<Card>();
      if (cards.size() >= 5 || replenish)
      {
         Card lastCard = null;
         for (Card card : cards)
         {
            if (straight.size() != 5) // don't look any futher cause we found a straight
            {
               if (lastCard == null || lastCard.getValue().ordinal() != card.getValue().ordinal())// skip duplicate cards
               {
                  if (lastCard != null && lastCard.getValue().ordinal() != card.getValue().ordinal() - 1) // create a new straight list if cards don't follow up
                  {
                     if (replenish)
                     {
                        replenishTillNextCard(lastCard, card, straight);
                     }
                     else
                     {
                        straight = new ArrayList<Card>();
                     }
                  }
                  if (straight.size() < 5) // if five cards are added the highest straight is found
                  {
                     straight.add(card);
                  }
                  lastCard = card;
               }
            }
         }
         // check for lowest straight (ACE, TWO, THREE, FOUR, FIVE)
         Card firstCard = cards.get(0);
         if (straight.size() == 4 && lastCard != null && firstCard != null &&
                 lastCard.getValue() == Card.Value.TWO &&
                 firstCard.getValue() == Card.Value.ACE)
         {
            straight.add(firstCard);
         }
         if (replenish && cards.size() < 5)
         {
            replenishTillNextCard(lastCard, lastCard, straight);
         }
      }
      return straight;
   }

   private static void replenishTillNextCard(Card lastCard, Card card, ArrayList<Card> straight)
   {
      Card.Value lastValue = lastCard.getValue();
      int newValueOrdinal = lastValue.ordinal() + 1;
      // replenish cards until the current card fits in or the total of 5 cards is reached.
      while (newValueOrdinal != card.getValue().ordinal()
              && straight.size() < 5)
      {
         Card.Value newCardValue = Card.Value.values()[newValueOrdinal];
         Card newCard = new Card(newCardValue, lastCard.getSuit());
         straight.add(newCard);
         newValueOrdinal++;
      }
   }


}
